// ml:run = $bin < input
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>

using ll = long long;
ll const maxn = 300;
ll cost[maxn];
ll prof[maxn];
ll tim[maxn];
std::vector<std::vector<ll>> rely;
ll n, m;
ll l;
ll ans;


template <class T>
struct dinic
{
	typedef T value_type;
	typedef ll size_type;
	typedef std::vector<size_type>::iterator edge_iter;

	struct edge {
		size_type from, to;
		value_type capacity, flow;
	};

	dinic(size_type num) : size(num)
	{
		graph.resize(num);	//[0, num)
		dist.resize(num);	//[0, num)
	}

	void add_edge(ll u, ll v, value_type cap = capacity_inf)
	{
		edge tmp;
		tmp.from = u; tmp.to = v; tmp.capacity = cap; tmp.flow = 0;
		edges.push_back(tmp);
		graph[u].push_back(edges.size() - 1);

		tmp.from = v; tmp.to = u; tmp.capacity = 0; tmp.flow = 0;
		edges.push_back(tmp);
		graph[v].push_back(edges.size() - 1);
	}

	bool bfs_label(size_type source, size_type target)
	{
		std::fill(dist.begin(), dist.end(), -1);
		std::queue<size_type> q;
		q.push(source);
		dist[source] = 0;
		while (!q.empty()) {
			size_type now = q.front();
			q.pop();
			for (edge_iter it = graph[now].begin(); it != graph[now].end(); ++it) {
				edge e = edges[*it];
				if (dist[e.to] == -1 && e.capacity > e.flow) {
					q.push(e.to);
					dist[e.to] = dist[now] + 1;
				}
			}
		}
		return dist[target] != -1;
	}

	value_type dfs(size_type v, size_type target, value_type f)
	{
		if (v == target || !f) return f;
		value_type block_flow = 0;
		for (edge_iter it = graph[v].begin(); it != graph[v].end(); ++it) {
			edge & e = edges[*it];
			if (e.capacity > e.flow && dist[e.to] == dist[v] + 1) {
				value_type tmp = dfs(e.to, target,
						std::min(e.capacity - e.flow, f - block_flow));
				block_flow += tmp;
				e.flow += tmp;
				edges[(*it) ^ 1].flow -= tmp;
			}
		}
		if (!block_flow) dist[v] = -1;
		return block_flow;
	}

	value_type max_flow(size_type source, size_type target)
	{
		value_type flow = 0;
		for (ll tmp; bfs_label(source, target); )
			while ((tmp = dfs(source, target, capacity_inf))) flow += tmp;
		return flow;
	}

//private:
	value_type static const capacity_inf = 1 << 28;
	size_type size;
	std::vector<ll> dist;
	std::vector<edge> edges;
	std::vector<std::vector<size_type>> graph;
};


void init()
{
    rely.clear();
    rely.resize(m + 1);
    ans = 0;
}

bool vis[maxn];

bool judge(ll mid)
{
    dinic<ll> d(n + m + 4);
    ll s = 0, t = n + m + 1;
    ll sum = 0;
    for (ll i = 1; i <= n; i++) {
        vis[i] = false;
        if (tim[i] <= mid) {
            vis[i] = true;
            d.add_edge(i, t, cost[i]);
        }
    }
    for (ll i = 1; i <= m; i++) {
        bool ok = true;
        for (auto j : rely[i])
            if (!vis[j]) { ok = false; break; }
        if (!ok) continue;
        d.add_edge(s, n + i, prof[i]);
        for (auto j : rely[i]) d.add_edge(n + i, j);
        sum += prof[i];
    }

    auto tmp = d.max_flow(s, t);
    sum -= tmp;
    if (sum >= l) ans = sum;
    return sum >= l;
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    ll T; std::cin >> T;
    for (ll ti = 1; ti <= T; ti++) {
        std::cout << "Case #" << ti << ": ";
        std::cin >> n >> m >> l;
        init();

        ll maxt = 0;
        for (ll i = 1; i <= n; i++) {
            std::cin >> cost[i] >> tim[i];
            maxt = std::max(maxt, tim[i]);
        }
        for (ll i = 1; i <= m; i++) {
            std::cin >> prof[i];
            ll k; std::cin >> k;
            for (ll j = 1, id; j <= k; j++) {
                std::cin >> id;
                rely[i].push_back(id);
            }
        }

        ll l = 0, r = maxt + 1;
        while (l + 1 < r) {
            ll mid = (l + r) / 2;
            if (judge(mid)) r = mid;
            else l = mid;
        }
        if (judge(l)) r = l;
        if (!judge(r))
            std::cout << "impossible\n";
        else
            std::cout << r << " " << ans << "\n";
    }
}

